package com.tx.java8.stream;

import com.tx.java8.consts.Status;
import com.tx.java8.domain.Employee;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 流式操作中的终止操作
 */
@SpringBootTest
public class StreamTest3 {
    List<Employee> employees = Arrays.asList(
            new Employee("adeep",1,99999.99, Status.BUSY),
            new Employee("mercury",15,50000, Status.BUSY),
            new Employee("张三",30,1200, Status.FREE),
            new Employee("张三2号",30,1100, Status.BUSY),
            new Employee("李四",35,6500, Status.FREE),
            new Employee("王五",50,7000, Status.BUSY),
            new Employee("王五66",50,7000, Status.FREE),
            new Employee("王五2",50,7000, Status.BUSY)
    );
    /**
     * 查找与匹配
     * allMatch--检查是否匹配所有元素
     * anyMatch--检查是否至少匹配一个元素
     * noneMatch--检查是否没有匹配到所有元素
     * findFirst--返回第一个元素
     * findAny--返回当前流中的任意元素
     *
     * count--返回流中元素的总个数
     * max--返回流中最大值
     * min--返回流中最小值
    **/
    //查找
    @Test
    public void test1(){
        //allMatch
        boolean b1 = employees.stream().allMatch((e)->Status.BUSY.equals(e.getStatus())) ;
        System.out.println(b1);

        //anyMatch
        boolean b2 = employees.stream().anyMatch((e)->Status.BUSY.equals(e.getStatus()));
        System.out.println(b2);

        //noneMatch
        boolean b3 = employees.stream().noneMatch((e)->Status.BUSY.equals(e.getStatus()));
        System.out.println(b3);

        //findFirst
        Optional<Employee> op = employees.stream().
                filter((e)->e.getSalary() == 7000)
                .findFirst();
        System.out.println(op.get());

        //findAny
        Optional<Employee> op1 = employees.parallelStream().
                filter((e)->e.getSalary() == 7000)
                .findAny();
        System.out.println(op1.get());
    }

    //匹配
    @Test
    public void test2(){
        //count
        Long num = employees.stream().count();
        System.out.println(num);

        //max
        Optional<Employee> op = employees.stream()
                .max(Comparator.comparing(Employee::getSalary));
        System.out.println(op.get());

        //min
        //找到薪资最少的
        Optional<Double> op2 = employees.stream()
                .map((e)->e.getSalary())
                .min(Double::compareTo);
        System.out.println(op2.get());

    }
    
    /**
     * 规约：
     *      reduce 可以将流中元素反复结合起来，创建一个值
     *
     *      map-reduce模式
    **/
    @Test
    public void test3(){
        //1....10
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer sum = list.stream()
                        .reduce(0,(x,y)->x+y);
        System.out.println(sum);

        //工资总和
        Optional<Double> ssum = employees.stream()
                .map((e) -> e.getSalary())
                .reduce(Double::sum);
        System.out.println(ssum.get());
    }

    /**
     * 收集：
     *      将该流转换成其他形式。比如说把流中的薪资取出来放到list中
     *      其实就是通过某些策略，把数据收集起来，转换成其他的形式
     *
     *   Collectors工具类
    **/

    //简易使用
    @Test
    public void test7(){
        //转换成list
        List<Double> list = employees.stream()
                .map((e) -> e.getSalary())
                .collect(Collectors.toList());
        list.stream().forEach(System.out::println);

        //转换成其他数据类型
        HashSet set = employees.stream()
                .map((e) -> e.getSalary())
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(set);
    }

    //收集的几个例子
    @Test
    public void test4(){
        //总数
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);

        //总金额
        double sum =
            employees.stream()
                    .map((e) -> e.getSalary())
                    .collect(Collectors.summingDouble((d)->d));
        System.out.println(sum);

        //最大值
        Optional<Employee> sal =
                employees.stream()
                        .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary)));
        System.out.println(sal.get());

        //最小值
        Optional<Double> emps =
            employees.stream()
                    .map((e)->e.getSalary())
                    .collect(Collectors.minBy(Double::compare));
        System.out.println(emps.get());

    }

    //分组，根据状态分组，得到每个状态的员工
    //多级分组：根据多个属性来分组
    @Test
    public void test5(){
        //分组--按照e.getSalary分组
        Map<String,List<Employee>> map = employees.stream()
                .collect(Collectors.groupingBy((e)->{
                    if(e.getSalary() < 2000){
                        return "低层";
                    }else if(e.getSalary() < 8000 && e.getSalary() >= 2000){
                        return "一般";
                    }else{
                        return "有钱";
                    }
                }));
        System.out.println(map);

        System.out.println("----------------------------------");

        //多级分组
        //先根据状态分组，再根据年龄分组
        Map<Status,Map<String,List<Employee>>> list = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus,Collectors.groupingBy((e)->{
                    if(e.getAge() < 12){
                        return "小孩";
                    }else if(e.getSalary() < 20 && e.getSalary() >= 12){
                        return "大孩";
                    }else{
                        return "老头";
                    }
                })));
        System.out.println(list);
    }

    //分区：满足条件一个区，不满足条件一个区
    @Test
    public void test6(){

        Map<Boolean, List<Employee>> list = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getAge() > 15));
        System.out.println(list);
    }


    //连接字符串
    @Test
    public void test8(){
        String str =
        employees.stream()
                .map((e)->e.getName())
                .collect(Collectors.joining(","));
        System.out.println(str);
    }
}
